#include "IOUringEventLoop.h"
#include "IOUringEventLoopThread.h"
#include "IOUringTcpServer.h"
#include "Logger.h"
#include <string.h>
using namespace std::placeholders;

class EchoServer {
  public:
    EchoServer(uint32_t numSubLoop, int port) : server_(numSubLoop, port) {
        server_.setNewConnectionCallback(
            std::bind(&EchoServer::handleAccept, this, _1, _2));
        server_.setReadCompleteCallback(
            std::bind(&EchoServer::handleRead, this, _1, _2));
        server_.setWriteCompleteCallback(
            std::bind(&EchoServer::handleWrite, this, _1, _2));
    }

    void start() { server_.start(); }

  private:
    IOUringTcpServer server_;

    void handleAccept(IOUringEventLoop *loop, struct io_uring_cqe *cqe) {
        int connfd = cqe->res;
        if (connfd >= 0) {
            loop->addRead(connfd, loop->ioUring()->kMaxMessageLen,
                          IOSQE_BUFFER_SELECT);
        }
    }

    void handleRead(IOUringEventLoop *loop, struct io_uring_cqe *cqe) {
        int bytesRead = cqe->res;
        int bid = cqe->flags >> 16;
        struct conn_info conni;
        memcpy(&conni, &cqe->user_data, sizeof(conni));

        if (cqe->res <= 0) {
            loop->addProvideBuf(bid);
            close(conni.fd_);
        } else {
            loop->addWrite(conni.fd_, bid, bytesRead, 0);
        }
    }

    void handleWrite(IOUringEventLoop *loop, struct io_uring_cqe *cqe) {
        struct conn_info conni;
        memcpy(&conni, &cqe->user_data, sizeof(conni));

        loop->addProvideBuf(conni.bid_);
        loop->addRead(conni.fd_, loop->ioUring()->kMaxMessageLen,
                      IOSQE_BUFFER_SELECT);
    }

}; // class EchoServer

int main() {
    EchoServer echoServer(1, 8000);
    echoServer.start();
}
